<template>
  <div class="menuMgt">
    <div class="menuWrap">
      <div class="block">
        <rail-tree ref="railTree" :tree-data="menuLst" @node-click="nodeClick" />
      </div>
    </div>
    <div class="menuDetail">
      <div class="menuDetailTitle">
        <div class="menuDetailTxt">当前正在对 [ {{ curMenuInfo.title }} ] 菜单权限进行 [
          <span v-if="handleType == 'see'">查看</span>
          <span v-if="handleType == 'add'">创建子菜单</span>
          <span v-if="handleType == 'edit'">编辑</span>
          <span v-if="handleType == 'del'">删除</span>
          ] 操作
        </div>
        <div>
          <el-button v-has="{code:'sys:permission:add',route:$route}" icon="el-icon-plus" type="primary" size="small" :disabled="handleType == 'add'" @click="handleAdd">
            新建</el-button>
          <el-button
            v-if="curMenuInfo.title != '首页'"
            v-has="{code:'sys:permission:edit',route:$route}"
            icon="el-icon-edit"
            type="primary"
            size="small"
            :disabled="handleType == 'edit'"
            @click="handleEdit"
          >编辑</el-button>
          <el-button
            v-if="curMenuInfo.title != '首页'"
            v-has="{code:'sys:permission:delete',route:$route}"
            icon="el-icon-delete"
            type="primary"
            size="small"
            @click="handleDel"
          >删除</el-button>
        </div>
      </div>
      <div class="menuInfo">
        <el-form ref="form" :rules="rules" :model="form" label-width="150px" class="menuForm">
          <h4 class="configTitle">菜单配置</h4>
          <el-form-item :label="handleType == 'add'?'子菜单名：':'菜单名：' " prop="title">
            <span v-if="handleType == 'see'">{{ form.title }}</span>
            <el-input v-else v-model="form.title" />
          </el-form-item>
          <el-form-item :label="'菜单标识符：' " prop="code">
            <span v-if="handleType == 'see'">{{ form.code }}</span>
            <el-input v-else v-model="form.code" />
          </el-form-item>
          <el-form-item label="icon：">
            <span v-if="handleType == 'see'">{{ form.icon }}</span>
            <!-- <el-select class="iconSelect" v-else v-model="form.icon" placeholder="请选择">
              <el-option v-for="item in iconLst" :key="item.icon" :label="item.icon" :value="item.icon">
                <span :class="item.icon" style="margin-right:15px"></span>
                <span>{{ item.icon }}</span>
              </el-option>
            </el-select> -->
            <el-autocomplete
              v-else
              v-model="form.icon"
              :fetch-suggestions="querySearch"
              placeholder="请输入icon样式"
            />
            <i :class="form.icon" style="margin-left:15px" />
          </el-form-item>
          <el-form-item label="上级菜单名称：" prop="parentMenu">
            <span v-if="handleType == 'see'">{{ form.parentName }}</span>
            <!-- <el-input v-else v-model="form.parentName" disabled /> -->
            <el-select v-else v-model="form.parentId" class="iconSelect" placeholder="请选择" style="width:550px">
              <el-option v-for="item in parentMenuLst" :key="item.id" :label="item.name" :value="item.id" />
            </el-select>
          </el-form-item>
          <!-- 通过配置文件查找 -->
          <el-form-item label="项目URL：" prop="component">
            <span v-if="handleType == 'see'">@ /views/{{ form.component }} </span>
            <el-input v-else v-model="form.component">
              <template slot="prepend">@ /views/</template>
            </el-input>
          </el-form-item>
          <el-form-item label="routeName：" prop="name">
            <span v-if="handleType == 'see'">{{ form.name }} </span>
            <el-input v-else v-model="form.name" />
          </el-form-item>
          <el-form-item label="routePath：" prop="path">
            <span v-if="handleType == 'see'">{{ form.path }} </span>
            <el-input v-else v-model="form.path" />
          </el-form-item>
          <el-form-item label="重定向：" prop="redirect">
            <span v-if="handleType == 'see'">{{ form.redirect }} </span>
            <el-input v-else v-model="form.redirect" />
          </el-form-item>
          <el-form-item label="菜单状态：">
            <span v-if="handleType == 'see'">
              {{ form.hidden?'隐藏':'显示' }}
            </span>
            <!-- <el-switch v-else v-model="form.hidden"></el-switch> -->
            <el-radio-group v-else v-model="form.hidden">
              <el-radio :label="false">显示</el-radio>
              <el-radio :label="true">隐藏</el-radio>
            </el-radio-group>
          </el-form-item>
          <el-form-item :label="'菜单排序：' " prop="sort">
            <span v-if="handleType == 'see'">{{ form.sort }}</span>
            <el-input v-else v-model="form.sort" type='number'/>
          </el-form-item>
          <el-form-item label="备注：" prop="remark">
            <span v-if="handleType == 'see'">{{ form.remark }}</span>
            <el-input v-else v-model="form.remark" type="textarea" />
          </el-form-item>
          <h4 class="configTitle">按钮配置</h4>
          <div style="padding-left:80px">
            <span v-for="tag in form.btnPermission" :key="tag.id">
              <el-tag
                v-if="tag.actionType != 1"
                style="margin-right:5px;margin-bottom:5px"
                :disable-transitions="true"
                :closable="handleType == 'edit' || handleType == 'add'"
                @close="handleDelTag(tag)"
              >
                {{ tag.name }} ({{ tag.code }})
              </el-tag>
            </span>
            <el-button
              v-if="handleType == 'add' || handleType == 'edit'"
              class="button-new-tag"
              size="small"
              @click="addTag"
            >+ 按钮</el-button>
            <span v-if="handleType == 'see' && (!form.btnPermission || form.btnPermission.length==0)">无</span>
          </div>

        </el-form>
        <div style="margin-top:15px;display:flex;justify-content:center">
          <el-button v-if="handleType == 'edit' || handleType == 'add'" type="primary" @click="submitForm('form')">确定保存
          </el-button>
          <el-button v-if="handleType == 'edit' || handleType == 'add'" @click="resetForm('form')">取消
          </el-button>
        </div>
      </div>
    </div>

    <el-dialog title="新建按钮" :visible.sync="tagFormVisible" @close="resetTagForm('tagForm')">
      <el-form ref="tagForm" :rules="tagRules" :model="tagForm" label-width="100px" style="width:500px">
        <el-form-item label="按钮名称:" prop="name">
          <el-input v-model="tagForm.name" autocomplete="off" />
        </el-form-item>
        <el-form-item label="按钮Code:" prop="code">
          <el-input v-model="tagForm.code" autocomplete="off" />
        </el-form-item>
        <el-form-item label="按钮描述:" prop="remark">
          <el-input v-model="tagForm.remark" autocomplete="off" />
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="resetTagForm('tagForm')">取 消</el-button>
        <el-button type="primary" @click="submitTagForm('tagForm')">确 定</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import {
  mapGetters
} from 'vuex'
import {
  deepClone
} from '@/utils'
import railTree from './components/railTree'
import {
  v4 as uuidv4
} from 'uuid'
import utilMenu from '@/utils/formatRoute.js'

const defaultForm = {
  title: '',
  icon: '',
  parentId: '',
  parentName: '',
  path: '',
  remark: '',
  btnPermission: [],
  type: 1,
  component: 'layout/index',
  name: '',
  hidden: false,
  redirect: '',
  sort:0
}
export default {
  name: '',
  components: {
    railTree
  },
  data() {
    return {
      parentName: '',
      rules: {
        name: [{
          required: true,
          message: '必填',
          trigger: 'blur'
        }, {
          validator: function(rule, value, callback) {
            if (/[a-zA-z]$/.test(value) == false) {
              callback(new Error('只能输入英文'))
            } else {
              callback()
            }
          },
          trigger: 'blur'
        }],
        title: [{
          required: true,
          message: '必填',
          trigger: 'blur'
        }],
        path: [{
          required: true,
          message: '必填',
          trigger: 'blur'
        }],
        component: [{
          required: true,
          message: '必填',
          trigger: 'blur'
        }],
        code: [{
          required: true,
          message: '必填',
          trigger: 'blur'
        }],
        sort:[{
          required: true,
          message: '必填',
          trigger: 'blur'
        }]
      },
      tagRules: {
        name: [{
          required: true,
          message: '必填',
          trigger: 'blur'
        }],
        code: [{
          required: true,
          message: '必填',
          trigger: 'blur'
        }]
      },
      tagForm: {
        name: '',
        code: '',
        remark: '',
        type: 2,
        actionType: 0 // 0:新增，1：减少
      },
      tagFormVisible: false,
      handleType: 'see',
      form: Object.assign({}, defaultForm),
      // treeConfig: {
      //   defaultExpandAll: false, // 是否全部展开,默认:false
      //   defaultExpandedKeys: [], // 默认打开菜单节点数组,只展开菜单，操作按钮不展示
      //   allKeys: [], // 所有节点id
      //   notExpandedKeys: [], // 不包含展开的id
      //   showCheckbox: false,
      //   defaultCheckedKeys: []
      // },
      curMenuInfo: {
        title: ''
      },
      defaultProps: {
        children: 'children',
        label: (data, node) => {
          return data.meta.title
        }
      },
      iconLst: [{
        icon: 'el-icon-user',
        value: 'el-icon-user'
      },
      {
        icon: 'el-icon-user-solid',
        value: 'el-icon-user-solid'
      },
      {
        icon: 'el-icon-s-order',
        value: 'el-icon-s-order'
      },
      {
        icon: 'el-icon-menu',
        value: 'el-icon-menu'
      },
      {
        icon: 'el-icon-setting',
        value: 'el-icon-setting'
      },
      {
        icon: 'el-icon-s-platform',
        value: 'el-icon-s-platform'
      },
      {
        icon: 'el-icon-s-grid',
        value: 'el-icon-s-grid'
      }
      ],
      parentMenuLst: [],
      menuLst: []
    }
  },
  computed: {
    // ...mapGetters([
    //   'menus'
    // ])
  },
  watch: {
    'form.parentId': {
      handler: function() {
        const id = this.form.parentId
        let parentName = '无'
        this.parentMenuLst.forEach(item => {
          if (item.id == id) parentName = item.name
        })
        this.form.parentName = parentName
      },
      deep: true
    }
  },
  created() {},
  async mounted() {
    this.getParentMenuLst()
    await this.getMenus()
    this.getCurMenuInfo()
  },
  methods: {
    createFilter(queryString) {
      return (iconLst) => {
        return (iconLst.value.toLowerCase().indexOf(queryString.toLowerCase()) === 0)
      }
    },
    querySearch(queryString, cb) {
      var iconLst = this.iconLst
      var results = queryString ? iconLst.filter(this.createFilter(queryString)) : iconLst
      // 调用 callback 返回建议列表的数据
      cb(results)
    },
    resetForm(formName) {
      this.$refs[formName].resetFields()
      this.getCurMenuInfo()
      this.handleType = 'see'
    },
    async submitForm(formName) {
      const type = this.handleType
      let keyLst = []
      this.$refs[formName].validate(async(valid) => {
        if (valid) {
          const form = this.form
          const params = {}
          const btnPermission = []
          if (type == 'add') { // 新增的数据格式修改
            form.btnPermission.forEach(item => {
              if (item.actionType == 0) {
                delete item.id
                btnPermission.push(item)
              }
            })
            keyLst = ['btnPermission', 'icon', 'parentId', 'parentName', 'remark', 'code', 'type', 'path',
              'title', 'name', 'component', 'hidden', 'redirect','sort'
            ]
          } else if (type == 'edit') { // 编辑的数据格式修改
            form.btnPermission.forEach(item => {
              const isNew = (typeof (item.id) === 'string')
              if (isNew) {
                delete item.id
                if (item.actionType == 0) btnPermission.push(item)
              } else {
                const btnObj = {}
                const btnKeyLst = ['id', 'name', 'code', 'remark', 'type', 'actionType']
                btnKeyLst.forEach(btnKey => {
                  btnObj[btnKey] = item[btnKey]
                })
                btnPermission.push(btnObj)
              }
            })
            keyLst = ['btnPermission', 'icon', 'parentId', 'parentName', 'remark', 'code', 'type', 'path',
              'title', 'id', 'name', 'component', 'hidden', 'redirect','sort'
            ]
          }
          keyLst.forEach(key => {
            let keyName = key
            if (key == 'path') keyName = 'url'
            if (key == 'name') keyName = 'routeName'
            if (key == 'title') keyName = 'name'
            params[keyName] = form[key]
          })
          params['url'] = params['url'].trim() // 去除url中的空格
          const {
            data
          } = await this.$API({
            method: 'post',
            url: '/api/permission/addNewPermission',
            data: params
          })
          if (data) {
            this.$message({
              type: 'success',
              message: '保存成功,准备刷新菜单……',
              duration: 40000
            })
            this.$router.go(0)
          } else {
            this.$message({
              type: 'error',
              message: '保存失败'
            })
          }
        } else {
          console.log('error submit!!')
          return false
        }
      })
    },
    async getMenus() {
      const {
        data
      } = await this.$API.post('/api/permission/queryPermissionList')
      this.menuLst = utilMenu.formatRoute(data)
    },
    async getParentMenuLst() {
      const {
        data
      } = await this.$API.post('/api/permission/queryMenuList')
      if (data) {
        this.parentMenuLst = data
        this.parentMenuLst.unshift({ name: '首页', id: 0 })
      }
    },
    handleDelTag(tag) {
      this.$confirm(`确定删除 [ ${tag.name} ] 按钮?`, '警告', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      })
        .then(async() => {
          const id = tag.id
          this.form.btnPermission.forEach(item => {
            if (item.id == id) { item.actionType = 1 }
          })
          this.$message({
            type: 'success',
            message: '删除成功!'
          })
        })
        .catch(err => {
          console.error(err)
        })
    },
    submitTagForm(formName) {
      this.$refs[formName].validate((valid) => {
        if (valid) {
          const tagObj = deepClone(this.tagForm)
          tagObj.id = uuidv4()
          this.form.btnPermission.push(tagObj)
          this.tagFormVisible = false
        } else {
          console.log('error submit!!')
          return false
        }
      })
    },
    resetTagForm(formName) {
      this.$refs[formName].resetFields()
      this.tagFormVisible = false
    },
    addTag() {
      this.tagFormVisible = true
    },
    handleAdd() {
      const {
        title,
        id
      } = this.curMenuInfo
      defaultForm.parentName = title
      defaultForm.parentId = id
      this.form = Object.assign({}, defaultForm)
      this.handleType = 'add'
    },
    handleEdit() {
      this.handleType = 'edit'
      this.getCurMenuInfo()
    },
    handleDel() {
      const curMenu = this.curMenuInfo
      const id = curMenu.id
      this.$confirm('确定删除当前菜单?', '警告', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      })
        .then(async() => {
          const {
            data
          } = await this.$API.post('/api/permission/deletePermissionByIdR', {
            id
          })

          this.$message({
            type: 'success',
            message: '删除成功!'
          })
          this.$router.go(0)
        })
        .catch(err => {
          console.error(err)
        })
    },
    nodeClick(arg) {
      this.$refs['form'].resetFields()
      const {
        data,
        node
      } = arg
      this.handleType = 'see'
      if (data.type && data.type == 'handleBtn') {
        const parentId = node.parent.data.id
        this.$nextTick(() => {
          this.$refs.railTree.$refs.menuTree.setCurrentKey(parentId)
        })
      }
      this.getCurMenuInfo()
    },
    remove(node, data) {
      const parent = node.parent
      const children = parent.data.children || parent.data
      const index = children.findIndex(d => d.id === data.id)
      children.splice(index, 1)
    },
    // 基于菜单数据，给菜单末节点添加btn数据
    filterAddBtnPermissionMenus(menus) {
      menus.forEach(item => {
        if (item.children) {
          this.filterAddBtnPermissionMenus(item.children)
        } else {
          if (item.meta.btnPermission) {
            const btnArr = item.meta.btnPermission
            item.children = []
            btnArr.forEach((btn, key) => {
              item.children.push({
                type: 'handleBtn', // 用以在菜单展示时，当前页面各种操作按钮此行，不显示（增删改）
                meta: {
                  title: btn.label,
                  id: btn.id
                }
              })
            })
          }
        }
      })
    },
    // 把meta里id调整到外层，配合el-tree的使用
    filterMenuId(menus) {
      menus.forEach(item => {
        const ID = item.meta.id
        item.id = ID
        if (item.children) this.filterMenuId(item.children)
      })
    },
    // 处理展开节点，操作的按钮收缩
    filterExpandId(menus) {
      this.filterNotExpandId(menus)
      const {
        allKeys,
        notExpandedKeys
      } = this.$refs.railTree.treeConfig
      allKeys.forEach(v => {
        if (notExpandedKeys.indexOf(v) === -1) this.treeConfig.defaultExpandedKeys.push(v)
      })
    },
    // 处理不展开的节点
    filterNotExpandId(menus) {
      menus.forEach(item => {
        this.$refs.railTree.treeConfig.allKeys.push(item.id)
        if (item.meta.btnPermission || item.type && item.type == 'handleBtn' || !item.children) {
          this.treeConfig.notExpandedKeys.push(item.id)
        }
        if (item.children) this.filterNotExpandId(item.children)
      })
    },
    filterMenus() {
      // this.$nextTick(() => {
      //   this.$refs.railTree.$refs.menuTree.setCurrentKey(0)
      // })
      // const rootMenus = [{ // 加入一个根菜单
      //   meta: {
      //     title: '菜单',
      //     parentId: null,
      //     id: 0,
      //     path:'/'
      //   },
      //   children: this.menus
      // }]
      // //this.filterAddBtnPermissionMenus(rootMenus) // 基于菜单数据，给菜单末节点添加btn数据
      // this.filterMenuId(rootMenus)
      // this.filterExpandId(rootMenus) // 处理展开节点
      // this.treeData = rootMenus

      this.getCurMenuInfo()
    },
    getCurMenuInfo() {
      this.$nextTick(() => {
        let curKey = this.$refs.railTree.$refs.menuTree.getCurrentKey()
        if(curKey == null) curKey = 0
        const {
          data
        } = this.$refs.railTree.$refs.menuTree.getNode(curKey)
        this.curMenuInfo = deepClone(data.meta)
        let [baseObj, metaObj, formObj] = [{}, {}, {}]
        const {
          meta
        } = data
        metaObj = deepClone(meta) // 获取到meta的对象
        for (const i in data) { // 获取到除去meta之外的对象
          if (i != 'meta') {
            baseObj[i] = data[i]
          }
        }
        formObj = Object.assign(baseObj, metaObj)
        this.form = deepClone(formObj)
      })
    }
  }
}

</script>
<style lang='scss' scoped>
  .menuMgt {
    width: 100%;
    height: calc(100vh - 80px);
    display: flex;
  }

  .menuWrap {
    width: 400px;
    border: 1px solid #ccc;
    height: 100%;
    overflow-y: auto;
    padding: 10px;
  }

  .menuDetail {
    flex: 1;
    padding: 10px;
    overflow-y: auto;

    .menuDetailTitle {
      display: flex;
      justify-content: space-between;
      align-items: center;
      margin-bottom: 15px;
      height: 33px;

      .menuDetailTxt {
        color: #818181;
        font-size: 14px;
      }
    }

  }

  .handlerBtn {
    display: none;
  }

  .btnConfigItem {
    display: flex;
    margin: 5px 0;
  }

  .button-new-tag {
    margin-left: 10px;
    height: 32px;
    line-height: 30px;
    padding-top: 0;
    padding-bottom: 0;
  }

  .configTitle {
    font-weight: 400;
    border-left: 4px solid #585757;
    padding-left: 10px;
    margin: 25px 0;
    color: #585757;
  }

</style>
<style scoped>
  .menuForm {
    width: 700px;
  }

</style>
<style>
  .custom-tree-node {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: space-between;
    font-size: 14px;
    padding-right: 8px;
  }

  .el-tree-node.is-current>.el-tree-node__content .handlerBtn {
    display: inline;
  }

</style>
